package com.kcs.dc.report.model.logic;

import java.sql.Connection;
import java.sql.SQLException;
import com.authen.ldap.KCS_LDAPEntry;
import com.authen.ldap.LDAPUtil;
import com.kcs.common.framework.GenericDto;
import com.kcs.common.utils.Based64Utils;
import com.kcs.common.utils.ConnectionUtils;
import com.kcs.common.utils.Constant;
import com.kcs.common.utils.ConstantMessage;
import com.kcs.common.utils.EventFactory;
import com.kcs.common.utils.LogWriter;
import com.kcs.common.utils.PropsUtils;
import com.kcs.common.utils.commonUtils;
import com.kcs.dc.report.model.dao.CommonDAO;
import com.kcs.dc.report.model.dao.userprofileDAO;
import com.kcs.dc.report.model.dao.model.utilGridInfoModel;
import com.kcs.dc.report.view.dto.MainMenuDto;
import com.kcs.dc.report.view.dto.UserProfileAddEditDto;
import com.kcs.dc.report.view.dto.UserProfileDto;

public class userprofileaddeditBL {

	private CommonDAO daoCommon = null;
	private userprofileDAO dao = null;
	private Connection conn = null;
	private String logoff = "LOGOFF";
	
	public userprofileaddeditBL() {
		daoCommon = new CommonDAO();
		dao = new userprofileDAO();
	}
	
	public GenericDto initEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start init(UserProfile Add & Edit) Event=====>", Constant.LOGGER_APPLICATION);
		
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{
			LogWriter.info("Step 1 : Check Authorized to use page.", Constant.LOGGER_APPLICATION);
			if(!commonBL.checkAuthenUsePage(dto.getUserId(), conn, "config.sys")){
				
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOHAVE_AUTHEN_PAGE, null);	        	
	        	dto.setService_id("welcome");
	        	
	        	// have error
				MainMenuDto menuDto = new MainMenuDto();
				menuDto.populate(dto);
				return menuDto;	
	        	
			}else{
				// Get Menu
				LogWriter.info("Step 2 : Get information by userId.", Constant.LOGGER_APPLICATION);
				// Case add : default get menu by login user.
				getInfoUser(dto, conn, true);
				dto.setService_id("userprofileadd");
			}
	
		}catch(Exception e){
			LogWriter.error("Exception userprofileaddeditBL [Method : initEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		return dto;
	}	
	
	public GenericDto saveAddEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start saveAdd(UserProfile Add & Edit) Event=====>", Constant.LOGGER_APPLICATION);
		
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		boolean isError = false;
		
		try{
			LogWriter.info("Step 1 : Check validate userId & ExpireDate", Constant.LOGGER_APPLICATION);
			if(dto.getUseridSearch().equals("")){
				dto.setFocus_Attr("useridSearch");
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_USER_BLANK, null);
				dto.setUseridSearch_Attr(Constant.ERR_ATTR);
				
				isError = true;				
			}else if(!dto.getUserId().equals(PropsUtils.getMessage(Constant.PROP_OTHER, "user.admin")) && !checkLDAP(dto)){				  
		    	dto.setFocus_Attr("useridSearch");
				dto.setUseridSearch_Attr(Constant.ERR_ATTR);
		    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOT_IN_LDAP, null);
		    	
				isError = true;
			}else if(!dto.getExpireDate().equals("")){ //check format date.
				if(!commonUtils.isValidDateFormat(dto.getExpireDate())){					
					dto.setExpireDate_Attr(Constant.ERR_ATTR);					
					dto.setFocus_Attr("expireDate");
					dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INVALID_FORMATE_DATE, null);
					
					isError = true;
				}																		
			}else if(commonBL.checkAuthenUsePage(dto.getUseridSearch(), conn, "config.sys")){
				dto.setFocus_Attr("useridSearch");
				dto.setUseridSearch_Attr(Constant.ERR_ATTR);
		    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_DUP_USER, null);
		    	
				isError = true;
			}
			
			// Have error.
			if(isError){	
				LogWriter.info("Step 1.1 : Have error while check validate data.", Constant.LOGGER_APPLICATION);
				keepOldValueWhenHaveError(dto, conn, true);
				dto.setService_id("userprofileadd");
				
				return dto;
			}
			
			
			/* Confirm save(add) information */		
			confirmSave(dto, conn, true);
			clearScreen(dto);
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.INF_UPD_SUCCESS, null);
			dto.setService_id("userprofileadd");

		}catch(Exception e){
			LogWriter.error("Exception userprofileaddeditBL [Method : saveEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		return dto;
	}
	
	public GenericDto glassEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start magglass click(UserProfile Add & Edit) Event=====>", Constant.LOGGER_APPLICATION);
	
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{			
			if(!checkLDAP(dto)){				  
		    	dto.setFocus_Attr("useridSearch");
				dto.setUseridSearch_Attr(Constant.ERR_ATTR);
		    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOT_IN_LDAP, null);
			}	
			
			keepOldValueWhenHaveError(dto, conn, true);
			dto.setService_id("userprofileadd");
	
		}catch(Exception e){
			LogWriter.error("Exception userprofileaddeditBL [Method : glassEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		return dto;
	}	
	
	public GenericDto editEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start edit(UserProfile Add & Edit) Event=====>", Constant.LOGGER_APPLICATION);
		
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{
			LogWriter.info("Step 1 : Check Authorized to use page.", Constant.LOGGER_APPLICATION);
			if(!commonBL.checkAuthenUsePage(dto.getUserId(), conn, "config.sys")){
				
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOHAVE_AUTHEN_PAGE, null);	        	
	        	dto.setService_id("welcome");
	        	
	        	// have error
				MainMenuDto menuDto = new MainMenuDto();
				menuDto.populate(dto);
				return menuDto;	
	        	
			}else{	
				// Get information by userId.
				LogWriter.info("Step 2 : Get information by userId.", Constant.LOGGER_APPLICATION);
				getInfoUser(dto, conn, false);	
				
				if (dto.getRow() == 0){
					LogWriter.info("Step 3 : Can't view information of userId : " + dto.getUseridSearch() + " because don't have in system."
							, Constant.LOGGER_APPLICATION);
					// Don't have data.
					dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_USER_DELETED, new String[]{dto.getUseridSearch()});
					dto.setService_id("userprofile");
		        	
		        	// have error
					EventFactory event = new EventFactory();
					UserProfileDto genericDto = new UserProfileDto();
					genericDto.populate(dto);
					genericDto = (UserProfileDto) event.executeBL("userprofile", "init", genericDto);
					
					return genericDto;
						
				}
				
				dto.setService_id("userprofileedit");
			}
	
		}catch(Exception e){
			LogWriter.error("Exception userprofileaddeditBL [Method : editEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		return dto;
	}
	
	public GenericDto refreshEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start Refresh(UserProfile Add & Edit) Event=====>", Constant.LOGGER_APPLICATION);
	
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{			
			if(!checkLDAP(dto)){	
		    	dto.setConfirmMessage(PropsUtils.getMessage(Constant.PROP_REPORT, ConstantMessage.WAR_NOT_LDAP_AND_DEL));
			}	
			
			keepOldValueWhenHaveError(dto, conn, false);
			dto.setService_id("userprofileedit");
	
		}catch(Exception e){
			LogWriter.error("Exception userprofileaddeditBL [Method : glassEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		return dto;
	}	
	
	public GenericDto saveChangeEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start saveChange(UserProfile Add & Edit) Event=====>", Constant.LOGGER_APPLICATION);
		
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{			
			if(haveChangeInfo(dto)){
				LogWriter.info("Step 1.1 : Have edit.", Constant.LOGGER_APPLICATION);
				
				//check format date.
				if(!dto.getExpireDate().equals("")){
					if(!commonUtils.isValidDateFormat(dto.getExpireDate())){
					
						keepOldValueWhenHaveError(dto, conn, false);
						dto.setExpireDate_Attr(Constant.ERR_ATTR);
						dto.setFocus_Attr("expireDate");
						dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INVALID_FORMATE_DATE, null);
						dto.setService_id("userprofileedit");
						
						return dto;
					}
				}
				
				// Confirm update information.
				confirmSave(dto, conn, false);
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.INF_UPD_SUCCESS, null);
				dto.setService_id("userprofileedit");
													
			}else{
				LogWriter.info("Step 1.1 : Not edit.", Constant.LOGGER_APPLICATION);
				// Dont' edit information.
				getInfoUser(dto, conn, false);
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOT_EDIT_DATA, null);
				dto.setService_id("userprofileedit");						
				
			}								
			
	
		}catch(Exception e){
			LogWriter.error("Exception userprofileaddeditBL [Method : saveChangeEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		return dto;
	}	
	
	public GenericDto backEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start back(UserProfile Add & Edit) Event=====>", Constant.LOGGER_APPLICATION);
		
		try{
			LogWriter.info("Step 1 : Initial back go to UserProfile Page.", Constant.LOGGER_APPLICATION);
			EventFactory event = new EventFactory();
			UserProfileDto genericDto = new UserProfileDto();
			genericDto.populate(dto);
			genericDto = (UserProfileDto) event.executeBL("userprofile", "init", genericDto);
			
			return genericDto;
	
		}catch(Exception e){
			LogWriter.error("Exception userprofileaddeditBL [Method : backEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}
		
		return dto;
	}	
	
	public GenericDto deleteEvent(UserProfileAddEditDto dto) throws Exception{
		
		LogWriter.info("<=====Start delete(UserProfile) Event=====>", Constant.LOGGER_APPLICATION);
		
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{
			LogWriter.info("Step 1 : Delete by userId", Constant.LOGGER_APPLICATION);
			
			dao.deleteUser(dto.getUseridSearch(), dto.getUserId(), conn);
			
			// Back to UserProfile Page.
			EventFactory event = new EventFactory();
			UserProfileDto genericDto = new UserProfileDto();
			genericDto.populate(dto);
			genericDto = (UserProfileDto) event.executeBL("userprofile", "init", genericDto);
			
			return genericDto;
			
		}catch(Exception e){
			LogWriter.error("userprofileaddeditBL [Method : deleteEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		return dto;				
	}
	

	private void getInfoUser(UserProfileAddEditDto dto, Connection conn, boolean caseAdd) throws SQLException{
		
		utilGridInfoModel model = null;
		String[] menuEachUser = null;
        
		try{ 
			model = daoCommon.getAllUserActive((caseAdd == true)? dto.getUserId() : dto.getUseridSearch(), "", "", conn);
  	
	        if (model != null ) { 
	        	dto.setColumnField(model.getColunmName());
	        	dto.setColumn(model.getColumn());
	        	dto.setRow(model.getRow());
	        	dto.setUserProfile(model.getGridInfo());
	        	
	        	// Loop set value of each menu (index 9 up.) : SYSTEM SETUP, SETTLE DEALS, ...
	        	menuEachUser = new String[dto.getColumn() - 9];
	        	for (int i = 0; i < menuEachUser.length; i++) {
	        		if(caseAdd){
	        			menuEachUser[i] = "N";
	        		}else{
	        			menuEachUser[i] = dto.getUserProfile()[0][i+9];
	        		}
				}
	        	// ExpireDate is column No.4
	        	if(model.getGridInfo() != null){
	        		dto.setExpireDate(dto.getUserProfile()[0][4]);
	        	}        	
	        	dto.setSelectMenu(menuEachUser);
	        } 
  
		}catch(SQLException e){
			LogWriter.error("userprofileaddeditBL [Method : getInfoUser] : " + e.getMessage(), Constant.LOGGER_APPLICATION);
			throw new SQLException();
		}
	}
	
	private boolean haveChangeInfo(UserProfileAddEditDto dto){
		LogWriter.info("Step 1 : Check, Have edit information?", Constant.LOGGER_APPLICATION);
		if(!dto.getHidExpireDate().equals(dto.getExpireDate())){
			return true;
		}
		
		for (int i = 0; i < dto.getSelectMenu().length; i++) {
			if(!dto.getHidselectMenu()[i].equals(dto.getSelectMenu()[i])){
				return true;
			}
		}
			
		return false;		
	}
	
	private void confirmSave(UserProfileAddEditDto dto, Connection conn, boolean caseAdd) throws SQLException{
		LogWriter.info("Step 2 : Confirm Save.", Constant.LOGGER_APPLICATION);
		
		try{ 
			for (int i = 0; i < dto.getSelectMenu().length; i++) {
				System.out.println(dto.getUseridSearch()+":"
							+dto.getUserId() +":"
							+dto.getUsernameSearch()+":"
							+dto.getExpireDate()+":"
							+dto.getColumnField()[i]+":"
							+dto.getSelectMenu()[i]);
				
				dao.updateUser(dto.getUseridSearch(), 
							dto.getUserId(),
							dto.getUsernameSearch(), 
							dto.getExpireDate(), 
							dto.getColumnField()[i],
							dto.getSelectMenu()[i], 
							conn);
				
			}
			
			// Default case Add : Set menu 'LOGOFF' is 'Y'
			if(caseAdd){
				dao.updateUser(dto.getUseridSearch(), 
						dto.getUserId(),
						dto.getUsernameSearch(), 
						dto.getExpireDate(), 
						logoff,
						"Y", 
						conn);
			}
				
			// get lasted information
			getInfoUser(dto, conn, caseAdd);
		
		}catch(SQLException e){
			LogWriter.error("userprofileaddeditBL [Method : confirmSave] : " + e.getMessage(), Constant.LOGGER_APPLICATION);
			throw new SQLException();
		}
				
	}
	
	private boolean checkLDAP(UserProfileAddEditDto dto){
	    
		LDAPUtil ldap = new LDAPUtil();   
		KCS_LDAPEntry ent = ldap.authenticateUser(dto.getUserId(),
										Based64Utils.base64decode(dto.getPasswordEncode()),
										dto.getUseridSearch());
	    
	    if (ent != null) 
	    	dto.setUsernameSearch(ent.getThaiFirstName() + " " + ent.getThaiLastName());
	        	       	
	    return (!commonUtils.trimAll(dto.getUsernameSearch()).equals("")) ? true : false ;

	}
	
	private void clearScreen(UserProfileAddEditDto dto){
		dto.setUseridSearch("");
		dto.setUseridSearch_Attr("");
		dto.setUsernameSearch("");
		dto.setExpireDate("");
		dto.setExpireDate_Attr("");
	}
	
	private void keepOldValueWhenHaveError(UserProfileAddEditDto dto,
			Connection conn, boolean caseAdd) throws Exception {
	
			/*
			 *  If have error and input expiredate and selectMenu then should be show old value.
			 */
			String oldExpireDate = dto.getExpireDate();
			String[] oldSelMenu = dto.getSelectMenu();	
						
			// Case add : default get menu by login user.
			// Case edit : use userId by link.
			getInfoUser(dto, conn, caseAdd);
							
			dto.setExpireDate(oldExpireDate);
			dto.setSelectMenu(oldSelMenu);
	
	}

}

